// TODO: I should try to figure out how to better integrate the sample and population measures so that they use each other better.
// TODO: ... For example, variance() basically recalculates moment_p(2,x) with a different conversion factor out front.


#ifndef STATSxx_STATISTICS_HPP
#define STATSxx_STATISTICS_HPP


// STL
#include <vector> // std::vector<>


// NOTE: The subroutines labeled "_p" should be used when one has access to the entire population x ...
// NOTE: ... otherwise, the unlabeled subroutines should be called.


namespace statistics
{
    template<typename T>
    T sum(
          const std::vector<T> &x
          );


    // TODO: NOTE: I think that mean() will need to be implemented individually for different data types (e.g., consider int, double, and std::complex<>).

    template<typename T>
    double mean(
                const std::vector<T> &x
                );

    template<typename T, typename N>
    double mean(
                const T _T,
                const N _N
                );


    template<typename T>
    double variance(
                    const std::vector<T> &x
                    );

    template<typename T, typename N>
    double variance(
                    const T _T,
                    const T _T2,
                    const N _N
                    );

    template<typename T>
    double variance_p(
                      const std::vector<T> &x
                      );


    template<typename T>
    double stddev(
                  const std::vector<T> &x
                  );

    template<typename T, typename N>
    double stddev(
                  const T _T,
                  const T _T2,
                  const N _N
                  );

    template<typename T>
    double stddev_p(
                    const std::vector<T> &x
                    );


    // DESC: Calculates the third *standardized* moment (skewness) of x.
    template<typename T>
    double skewness(
                    const std::vector<T> &x
                    );

    template<typename T>
    double skewness_p(
                      const std::vector<T> &x
                       );


    // DESC: Calculates the fourth *standardized* moment (kurtosis) of x, converted to *excess kurtosis*.
    template<typename T>
    double kurtosis(
                    const std::vector<T> &x
                    );

    template<typename T>
    double kurtosis_p(
                      const std::vector<T> &x
                      );


    double NMSE(
                const std::vector<double> &x,
                const std::vector<double> &y
                );

    double NMBF(
                const std::vector<double> &x0,
                const std::vector<double> &x
                );

    double r(
             const std::vector<double> &x,
             const std::vector<double> &y
             );

    double r2(
              const std::vector<double> &x,
              const std::vector<double> &y
              );


    template<typename T>
    double moment_p(
                    const int             n,
                    const std::vector<T> &x
                    );
}

#include "statsxx/statistics/sum.cpp"
#include "statsxx/statistics/mean.cpp"
#include "statsxx/statistics/variance.tpp"
#include "statsxx/statistics/variance_p.tpp"
#include "statsxx/statistics/stddev.tpp"
#include "statsxx/statistics/stddev_p.tpp"
#include "statsxx/statistics/skewness.tpp"
#include "statsxx/statistics/skewness_p.tpp"
#include "statsxx/statistics/kurtosis.tpp"
#include "statsxx/statistics/kurtosis_p.tpp"
#include "statsxx/statistics/NMSE.cpp"
#include "statsxx/statistics/NMBF.cpp"
#include "statsxx/statistics/r.cpp"
#include "statsxx/statistics/r2.cpp"
#include "statsxx/statistics/moment_p.tpp"


#endif
